﻿
using FaceWebServer.DB.System;
using FaceWebServer.Interface;
using FaceWebServer.Model.People;
using FaceWebServer.Utility;
using FaceWebServer.Utility.FilterAttribute;
using FaceWebServer.Utility.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using DoNetDrive.Common.Cryptography;
using FaceWebServer.Utility.ExpressionExtend;

namespace FC8280TServer.Controllers.People
{
    [Route("api/[controller]")]
    [ApiController]
    [Authorize]
    public class PeopleController : ControllerBase
    {

        private readonly ILogger<PeopleController> _logger;
        private IMyMemoryCache _Cache;
        private IPeopleService _PeopleDB;

        public PeopleController(ILogger<PeopleController> logger,
            IPeopleService peopledb, IMyMemoryCache mycache)
        {
            _logger = logger;
            _PeopleDB = peopledb;
            _Cache = mycache;
        }


        /// <summary>
        /// 获取已安装的人员表格
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("GetPeopleTable")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public IActionResult GetPeopleTable([FromForm] PeopleQueryParameter par)
        {

            List<Expression<Func<FacePeople, bool>>> oWheres = new();
            if (par.EmployeeID > 0) oWheres.Add(x => x.EmployeeID.Equals(par.EmployeeID));
            if (par.EmployeeIc > 0) oWheres.Add(x => x.EmployeeIc.Equals(par.EmployeeIc));
            if (par.EmployeePhoto > 0)
            {
                if (par.EmployeePhoto == 1)
                    oWheres.Add(x => x.PhotoLen > 0);
                else
                    oWheres.Add(x => x.PhotoLen == 0);
            }

            if (!string.IsNullOrWhiteSpace(par.EmployeeName)) oWheres.Add(x => x.EmployeeName.Contains(par.EmployeeName));
            if (!string.IsNullOrWhiteSpace(par.EmployeeJob)) oWheres.Add(x => x.EmployeeJob.Contains(par.EmployeeJob));
            if (!string.IsNullOrWhiteSpace(par.EmployeePhone)) oWheres.Add(x => x.EmployeePhone.Contains(par.EmployeePhone));
            _logger.LogInformation("获取人员列表");
            var peoples = _PeopleDB.QueryPage(
                x => new
                {
                    x.ID,
                    x.EmployeeID,
                    x.EmployeeName,
                    x.EmployeePassword,
                    x.EmployeeJob,
                    x.EmployeeIc,
                    x.EmployeePhoto,
                    x.PhotoLen,
                    x.EmployeePhone
                },
                oWheres, par.pageSize, par.pageIndex,
                x => x.EmployeeID,
                par.isAsc);

            return new JsonResult(new JsonResultModel(peoples));
        }

        /// <summary>
        /// 添加人员信息
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("AddAndFile")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public async Task<IActionResult> AddAndFile([FromForm] string postdata, [FromForm] IFormCollection files)
        {
            var oUpdatePar = JsonConvert.DeserializeObject<PeopleAddParameter>(postdata);
            IActionResult errResult = null;
            if (!VerifyActionFilterAttribute.VerifyEntity(typeof(PeopleAddParameter), oUpdatePar, r => errResult = r)) return errResult;

            return await Add(oUpdatePar, files);
        }

        /// <summary>
        /// 添加人员信息
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("Add")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public async Task<IActionResult> Add([FromForm] PeopleAddParameter par, [FromForm] IFormCollection files)
        {
            var people = new FacePeople();



            par.CopyTo(people);

            people.CreateTime = DateTime.Now;
            people.LastUpdatetime = DateTime.Now;

            #region 重复过滤
            List<Expression<Func<FacePeople, bool>>> oWheres = new();
            Expression<Func<FacePeople, bool>> w1 = x => x.EmployeeID.Equals(par.EmployeeID);
            Expression<Func<FacePeople, bool>> w2 = x => x.EmployeeIc.Equals(par.EmployeeIc);

            if (par.EmployeeID > 0)
                oWheres.Add(x => x.EmployeeID.Equals(par.EmployeeID));

            if (par.EmployeeIc > 0)
                oWheres.Add(x => x.EmployeeIc.Equals(par.EmployeeIc));

            var peoples = _PeopleDB.QueryPage(
                x => new
                {
                    x.ID,
                    x.EmployeeID,
                    x.EmployeeIc,
                    x.EmployeeName
                },
                oWheres, 100, 1,
                x => x.EmployeeID,
                true, false);
            if (peoples.TotalCount > 0)
            {
                foreach (var p in peoples.DataList)
                {
                    if (p.EmployeeID == par.EmployeeID)
                    {
                        return new JsonResult(new JsonResultModel(200, $"人员编号重复，重复人员名称：{p.EmployeeName}"));
                    }
                    if (par.EmployeeIc > 0 && p.EmployeeIc == par.EmployeeIc)
                    {
                        return new JsonResult(new JsonResultModel(201, $"人员卡号重复，重复人员名称：{p.EmployeeName}({p.EmployeeID})"));
                    }
                }

            }
            #endregion


            if (people.EmployeeID == 0)
            {
                lock (_Cache)
                {
                    //需要自动分配一个ID；
                    var sysdb = _PeopleDB.GetSystemKVDBSet();
                    var kv = sysdb.Find("AutoEmployeeID");
                    long iAutoEmployeeID = 10000;
                    if (kv == null)
                    {

                        kv = new() { Key = "AutoEmployeeID", Value = "10000" };
                        _PeopleDB.Insert<SystemKV>(kv);
                    }
                    else
                    {

                        iAutoEmployeeID = long.Parse(kv.Value);
                    }

                    var EmplIDs = new HashSet<long>(_PeopleDB.Query<FacePeople>(null).Select(p => p.EmployeeID));
                    do
                    {
                        if (!EmplIDs.Contains(iAutoEmployeeID))
                        {
                            people.EmployeeID = iAutoEmployeeID;
                            //iAutoEmployeeID++;
                            break;
                        }
                        iAutoEmployeeID++;
                    } while (true);


                    kv.LastUpdateTime = DateTime.Now;
                    kv.Value = iAutoEmployeeID.ToString();
                    _PeopleDB.Update(kv);
                }
            }


            #region 照片处理
            string sPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "People");
            if (!Directory.Exists(sPath))
            {
                Directory.CreateDirectory(sPath);
            }

            string sFileName = $"{people.EmployeeID}.jpg";
            if (par.EmployeePhotoWay.Equals("path"))
            {
                if (files.Files.Count == 1)
                {


                    string sFile = Path.Combine(sPath, sFileName);

                    var uploadFile = files.Files[0];
                    if (uploadFile.Length > 0)
                    {
                        if (uploadFile.Length > 20971520)//20*1024KB=20M
                        {
                            return new JsonResult(new JsonResultModel(202, "人员照片太大，请先压缩照片！"));
                        }

                        people.PhotoLen = (int)uploadFile.Length;
                        string crc;
                        using (var stream = new MemoryStream(people.PhotoLen))
                        {
                            await uploadFile.CopyToAsync(stream);
                            byte[] bImg = stream.ToArray();
                            bImg = DoNetDrive.Common.FaceImageUtil.ConvertImage(bImg);

                            crc = CRC32_C.CalculateDigest(bImg, 0, (uint)bImg.Length).ToString("x");
                            await System.IO.File.WriteAllBytesAsync(sFile, bImg);
                        }


                        people.EmployeePhoto = $"/People/{sFileName}?{crc}";
                    }
                }
                else
                {
                    return new JsonResult(new JsonResultModel(203, "人员照片参数错误！"));
                }
            }
            else if (par.EmployeePhotoWay.Equals("base"))
            {
                if (people == null) return new JsonResult(new JsonResultModel(204, "人员照片格式错误，请使用文件上传方式"));
            }
            else
            {
                //没有照片
                people.EmployeePhotoWay = string.Empty;
                people.PhotoLen = 0;
                people.EmployeePhoto = string.Empty;
            }
            #endregion


            _PeopleDB.AddUserLog("人员管理",
                $"添加人员：{people.EmployeeName}({people.EmployeeID}),职务：{people.EmployeeJob},卡号：{people.EmployeeIc},照片地址：{people.EmployeePhoto}",
                string.Empty, $"{people.EmployeeName}({people.EmployeeID})");
            _PeopleDB.Insert(people);
            _logger.LogInformation($"添加人员 ID:{people.ID} 编号：{people.EmployeeID} 姓名：{people.EmployeeName}");
            return new JsonResult(new JsonResultModel(new { people.ID }));
        }

        /// <summary>
        /// 更新人员信息
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("UpdateAndFile")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public async Task<IActionResult> UpdateAndFile([FromForm] string postdata, [FromForm] IFormCollection files)
        {
            var oUpdatePar = JsonConvert.DeserializeObject<PeopleUpdateParameter>(postdata);
            IActionResult errResult = null;
            if (!VerifyActionFilterAttribute.VerifyEntity(typeof(PeopleUpdateParameter), oUpdatePar, r => errResult = r)) return errResult;

            return await Update(oUpdatePar, files);
        }


        /// <summary>
        /// 更新人员信息
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("Update")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public async Task<IActionResult> Update([FromForm] PeopleUpdateParameter par, [FromForm] IFormCollection files)
        {
            var people = _PeopleDB.Find<FacePeople>(par.ID);
            if (people == null) return new JsonResult(new JsonResultModel(200, "人员不存在"));


            #region 重复过滤
            List<Expression<Func<FacePeople, bool>>> oWheres = new();
            Expression<Func<FacePeople, bool>> w1 = x => x.EmployeeID.Equals(par.EmployeeID);
            Expression<Func<FacePeople, bool>> w2 = x => x.EmployeeIc.Equals(par.EmployeeIc);

            oWheres.Add(x => x.ID != par.ID);
            //oWheres.Add(x => x.EmployeeID.Equals(par.EmployeeID));
            if (par.EmployeeIc > 0)
                oWheres.Add(w1.Or(w2));
            else
                oWheres.Add(w1);

            var peoples = _PeopleDB.QueryPage(
                x => new
                {
                    x.ID,
                    x.EmployeeID,
                    x.EmployeeIc,
                    x.EmployeeName
                },
                oWheres, 100, 1,
                x => x.EmployeeID,
                true, true);
            if (peoples.TotalCount > 0)
            {
                foreach (var p in peoples.DataList)
                {
                    if (p.EmployeeID == par.EmployeeID)
                    {
                        return new JsonResult(new JsonResultModel(201, $"人员编号重复，重复人员名称：{p.EmployeeName}"));
                    }
                    if (par.EmployeeIc > 0 && p.EmployeeIc == par.EmployeeIc)
                    {
                        return new JsonResult(new JsonResultModel(202, $"人员卡号重复，重复人员名称：{p.EmployeeName}({p.EmployeeID})"));
                    }
                }

            }
            #endregion


            string sOldEmployeePhotoWay = people.EmployeePhotoWay;
            par.CopyTo(people);
            _logger.LogInformation($"更新人员：ID:{people.ID} 编号：{people.EmployeeID} 姓名:{people.EmployeeName}");
            people.LastUpdatetime = DateTime.Now;

            #region 照片处理
            string sPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "People");
            if (!Directory.Exists(sPath))
            {
                Directory.CreateDirectory(sPath);
            }

            string sFileName = $"{people.EmployeeID}.jpg";
            if (par.EmployeePhotoWay.Equals("path"))
            {
                if (files.Files.Count == 1)
                {


                    string sFile = Path.Combine(sPath, sFileName);

                    var uploadFile = files.Files[0];
                    if (uploadFile.Length > 0)
                    {
                        if (uploadFile.Length > 20971520)//20*1024KB=20M
                        {
                            return new JsonResult(new JsonResultModel(203, "人员照片太大，请先压缩照片！"));
                        }

                        people.PhotoLen = (int)uploadFile.Length;

                        //using (var stream = new FileStream(sFile, FileMode.Create))
                        //{
                        //    await uploadFile.CopyToAsync(stream);
                        //}
                        string crc;
                        using (var stream = new MemoryStream(people.PhotoLen))
                        {
                            await uploadFile.CopyToAsync(stream);
                            byte[] bImg = stream.ToArray();
                            bImg = DoNetDrive.Common.FaceImageUtil.ConvertImage(bImg);

                            crc = CRC32_C.CalculateDigest(bImg, 0, (uint)bImg.Length).ToString("x");
                            await System.IO.File.WriteAllBytesAsync(sFile, bImg);
                        }


                        people.EmployeePhoto = $"/People/{sFileName}?{crc}";
                    }
                }
                else
                {
                    return new JsonResult(new JsonResultModel(204, "人员照片参数错误！"));
                }
            }
            else if (par.EmployeePhotoWay.Equals("base"))
            {
                if (people == null) return new JsonResult(new JsonResultModel(205, "人员照片格式错误，请使用文件上传方式"));
            }
            else if (par.EmployeePhotoWay.Equals("Delete"))
            {
                //删除照片
                if (people.PhotoLen > 0)
                {
                    people.EmployeePhotoWay = string.Empty;
                    sFileName = people.EmployeePhoto;
                    people.EmployeePhoto = string.Empty;
                    people.PhotoLen = 0;
                    //var sFile = sPath + sFileName;
                    var sFile = GetImageFileName(sFileName);

                    if (System.IO.File.Exists(sFile))
                        System.IO.File.Delete(sFile);
                }
            }
            else if (par.EmployeePhotoWay.Equals("NULL"))
            {
                //照片没有变化
                people.EmployeePhotoWay = sOldEmployeePhotoWay;
            }
            #endregion


            _PeopleDB.AddUserLog("人员管理",
    $"修改人员：{people.EmployeeName}({people.EmployeeID}),职务：{people.EmployeeJob},卡号：{people.EmployeeIc},照片地址：{people.EmployeePhoto}",
    string.Empty, $"{people.EmployeeName}({people.EmployeeID})");

            _PeopleDB.Update(people);

            return new JsonResult(new JsonResultModel(new { par.ID, people.PhotoLen, people.EmployeePhoto, people.EmployeePhotoWay }));
        }


        /// <summary>
        /// 从URL 连接中获取文件名，去掉末尾的?crc
        /// </summary>
        /// <param name="sPath"></param>
        /// <param name="sFileName"></param>
        /// <returns></returns>
        private string GetImageFileName(string sURL)
        {
            string sPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");


            var iIndex = sURL.LastIndexOf("?");
            if (iIndex > 0)
            {
                sURL = sURL.Substring(0, iIndex);
            }
            string[] sURLSegments = sURL.Split("/");
            string sFile = sPath;
            foreach (var sSegment in sURLSegments)
            {
                sFile = Path.Combine(sFile, sSegment);
            }
            return sFile;
        }

        /// <summary>
        /// 删除人员
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("Delete")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public async Task<IActionResult> Delete([FromForm] PeopleDeleteParameter par)
        {


            if (par.PeopleIDs == null)
            {
                return new JsonResult(new JsonResultModel(1, "未选择需要删除的人员"));
            }
            if (par.PeopleIDs.Count == 0)
            {
                return new JsonResult(new JsonResultModel(1, "未选择需要删除的人员"));
            }

            HashSet<int> peopleIDLists = new HashSet<int>(par.PeopleIDs);
            var peoplesDB = _PeopleDB.Query<FacePeople>(x => peopleIDLists.Contains(x.ID))
                .Select(x => new FacePeople { ID = x.ID, 
                    EmployeeName = x.EmployeeName, 
                    EmployeeID= x.EmployeeID, 
                    EmployeeJob= x.EmployeeJob, 
                    EmployeeIc = x.EmployeeIc,
                    EmployeePhoto=x.EmployeePhoto });

            await Task.Run(() =>
            {
                string sPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "People");
                if (!Directory.Exists(sPath))
                {
                    Directory.CreateDirectory(sPath);
                }
                foreach (var p in peoplesDB)
                {
                    _PeopleDB.AddUserLog("人员管理",
                $"删除人员：{p.EmployeeName}({p.EmployeeID}),职务：{p.EmployeeJob},卡号：{p.EmployeeIc},照片地址：{p.EmployeePhoto}",
                string.Empty, $"{p.EmployeeName}({p.EmployeeID})");


                    if (!string.IsNullOrWhiteSpace(p.EmployeePhoto))
                    {
                        var sFileName = GetImageFileName(p.EmployeePhoto);
                        if (System.IO.File.Exists(sFileName))
                        {
                            try
                            {
                                System.IO.File.Delete(sFileName);
                            }
                            catch (Exception ex)
                            {

                                _logger.LogError($" Delete 删除文件时发生错误：{sFileName}  {ex.Message} ");
                            }

                        }
                    }

                }
            });

            _PeopleDB.Delete(peoplesDB.AsEnumerable());
            _logger.LogInformation($"删除人员列表 ID列表：{string.Join(",", par.PeopleIDs.Select(id => id.ToString()))}");

            return new JsonResult(new JsonResultModel(par));
        }


        /// <summary>
        /// 获取人员详情
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [HttpGet]
        [Route("GetPeopleDetail/{ID}")]
        public IActionResult GetPeopleDetail(int ID)
        {
            var people = _PeopleDB.Find<FacePeople>(ID);
            if (people == null) return new JsonResult(new JsonResultModel(10, "人员不存在"));



            return new JsonResult(new JsonResultModel(people));
        }



    }
}
